package com.king.framework.base.service.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.king.common.exception.AssertHelper;
import com.king.common.utils.PageUtils;
import com.king.common.utils.SearchUtils;
import com.king.common.utils.SecurityUtils;
import com.king.common.utils.bean.BeanUtils;
import com.king.common.utils.uuid.SnowFlakeUtil;
import com.king.framework.base.domain.YyBaseEntity;
import com.king.framework.base.domain.vo.LoginUser;
import com.king.framework.base.domain.vo.PageResult;
import com.king.framework.base.service.YyBaseService;

/**
 * IService基本实现
 * @author yy-team
 * @date 2018年8月10日
 * @param <T>
 * @param <ID>
 */
@Service
@Transactional(readOnly = true, rollbackFor = { Exception.class })
public abstract class YyBaseServiceImpl<M extends BaseMapper<T>, T extends YyBaseEntity, ID extends Serializable> extends ServiceImpl<M, T> implements YyBaseService<T, ID> {

	private Class<T> persistentClass;
	
	@Autowired
	private com.baomidou.mybatisplus.extension.service.IService<T> service;

	/**
	 * getClass().getGenericSuperclass()返回表示此 Class 所表示的实体（类、接口、基本类型或 void） 的直接超类的 Type(Class
	 * <T>泛型中的类型)，然后将其转换ParameterizedType。。 getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。 [0]就是这个数组中第一个了。。
	 * 简而言之就是获得超类的泛型参数的实际类型。。
	 */
	@SuppressWarnings("unchecked")
	@PostConstruct
	protected void init() {
		// 当前对象的直接超类的 Type
		Type genericSuperclass = getClass().getGenericSuperclass();
		if (genericSuperclass instanceof ParameterizedType) {
			// 参数化类型
			ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
			// 返回表示此类型实际类型参数的 Type 对象的数组
			Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
			this.persistentClass = (Class<T>) actualTypeArguments[1];
		} else {
			this.persistentClass = (Class<T>) genericSuperclass;
		}
	}
	
	public void setBaseEntity(YyBaseEntity entity){
		if(entity.getId() == null){
			entity.setId(SnowFlakeUtil.getInstance().nextId());
		}
		LoginUser loginUser = SecurityUtils.getLoginUser();
		if (loginUser != null) {
			entity.setCr(loginUser.getUserId());
			entity.setMr(loginUser.getUserId());
			if(entity.getGroupid() == null){
				entity.setGroupid(loginUser.getGroupid());
			}
		}
		entity.setSs(1);
		entity.setCts(new Date());
		entity.setMts(new Date());
	}

    /**
     * 根据id查询，id为null，直接返回null
     *
     * @param id
     * @return
     */
//    public T getById(ID id) {
//        if (id == null) return null;
//        T t = null;
//        try {
//            t = this.findByPK(id);
//        } catch (Exception e) {
//            throw new ServiceException("根据id查询实体异常");
//        }
//        return t;
//    }

    /**
     * 根据id查询，不存在则抛出异常
     *
     * @param id
     * @return
     */
    public T getByIdOrExcep(ID id) {
        T t = this.getById(id);
        AssertHelper.getInstance().checkNullException(t, this.persistentClass.getSimpleName() + "实体不存在, id: " + id);
        return t;
    }

	@Override
	public T findByPK(ID id) throws Exception {
		AssertHelper.getInstance().checkNullException(id, "id不能为空");
		
		T entity = service.getById(id);
		processData(entity);
		return entity;
	}


	@Override
	public List<T> findByPKS(Collection<ID> idList) throws Exception {
		return service.listByIds(idList);
	}


	@Override
	public List<T> findAll() throws Exception {
		QueryWrapper<T> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("ss", 1);
		return service.list(queryWrapper);
	}



	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void beforeDelete(T entity) throws Exception {
		
	}

	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void doDelete(ID id) throws Exception {
		T entity = findByPK(id);
		AssertHelper.getInstance().checkNullException(entity, "找不到记录");
		doDelete(entity);
	}

	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void afterDelete(T entity) throws Exception {

	}

	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void doDelete(ID[] ids) throws Exception {
		for (ID id : ids) {
			doDelete(id);
		}
	}

	/**
	 * 业务底层删除方法
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void doDelete(T entity) throws Exception {
		beforeDelete(entity);
		service.removeById(entity);
//		entity.setSs(0);
//		doUpdate(entity);
		afterDelete(entity);
	}

	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void doDelete(Iterable<T> entities) throws Exception {
		for (T entity : entities) {
			doDelete(entity);
		}
	}


	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void doDeleteAll() throws Exception {
		QueryWrapper<T> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("ss", 1);
		service.remove(queryWrapper);
	}
	
	
	
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void beforeAdd(T entity) throws Exception {
		setBaseEntity(entity);
	}

	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public T doAdd(T entity) throws Exception {
		beforeAdd(entity);
//		beforeSave(entity);
		
		service.save(entity);

//		afterSave(entity);
		afterAdd(entity);
		return entity;
	}

	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public Iterable<T> doAdd(Iterable<T> entities) throws Exception {
		List<T> result = new ArrayList<T>();
		if (entities == null) {
			return result;
		}
		for (T entity : entities) {
			result.add(doAdd(entity));
		}
		return result;
	}
	
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void afterAdd(T entity) throws Exception {

	}
	

	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void beforeUpdate(T oldEntity, T entity) throws Exception {

	}

	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public void afterUpdate(T oldEntity, T entity) throws Exception {
	}


	/**
     * 仅仅更新不为null的字段，如果字段为null，则不更新该字段值
     *
     * @param entity
     * @return
     * @throws Exception
     */
	@SuppressWarnings("unchecked")
	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public T doUpdate(T entity) throws Exception {
		LoginUser loginUser = SecurityUtils.getLoginUser();
		if (loginUser != null) {
			entity.setMr(loginUser.getUserId());
		}
		entity.setMts(new Date());
		
		T currentEntity = null;
		if (entity.getId() != null) {
			currentEntity = findByPK((ID) entity.getId());
		}
		AssertHelper.getInstance().checkNullException(currentEntity, "找不到记录");
		
		AssertHelper.getInstance().checkException(!loginUser.isAdmin()&& currentEntity.getGroupid().longValue()!= loginUser.getGroupid(),
				"不属于所属集团,无权修改");
		
		// 复制旧的数据
		ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
        Class<T> clazz = (Class<T>) ptype.getActualTypeArguments()[1];
		T oldEntity = (T) clazz.newInstance();

		BeanUtils.copyBeanProp(oldEntity, currentEntity);

		// 复制传递过来的数据到 原实体上
		BeanUtils.copyNotNullProperties(entity, currentEntity);

		beforeUpdate(oldEntity, currentEntity);
//		beforeSave(currentEntity);
		
		// 更新
		service.updateById(currentEntity);
		
//		afterSave(currentEntity);

		afterUpdate(oldEntity, currentEntity);
		return currentEntity;
	}
	

	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public Iterable<T> doUpdate(Iterable<T> entities) throws Exception {
		List<T> result = new ArrayList<T>();
		if (entities == null) {
			return result;
		}
		for (T entity : entities) {
			result.add(doUpdate(entity));
		}
		return result;
	}


//	@Transactional(readOnly = false, rollbackFor = { Exception.class })
//	public void beforeSave(T entity) throws Exception {
//
//	}
//
//
//	@Transactional(readOnly = false, rollbackFor = { Exception.class })
//	public void afterSave(T newEntity) throws Exception {
//
//	}


	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public PageResult<T> doQuery(Map<String, Object> searchMap) throws Exception {
		PageUtils.startPage(searchMap);
		QueryWrapper<T> queryWrapper = SearchUtils.buildQueryWrapper(searchMap);
		List<T> list = service.list(queryWrapper);
		processData(list);
		PageInfo pageInfo = new PageInfo(list);
		return new PageResult(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), list);
	}
	
	
	
    @Transactional(readOnly = true, rollbackFor = {Exception.class})
    protected void processData(T entity) throws Exception {
    }
    
    @Transactional(readOnly = true, rollbackFor = {Exception.class})
    protected void processData(List<T> list) throws Exception {
    }
	


}
